﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace DLog.SqlServerDal
{
    public class Repository<T> where T : class
    {
        /// <summary>
        /// 上下文
        /// </summary>
        protected DLogContext Context;
        private bool shareContext = false;
        protected IDbSet<T> dbSet;
        /// <summary>
        /// 构造函数
        /// </summary>
        public Repository()
        {
            Context = new DLogContext();
            dbSet = Context.Set<T>();
        }
        /// <summary>
        /// 有参构造函数
        /// </summary>
        /// <param name="context"></param>
        public Repository(DLogContext context)
        {
            Context = context;
            dbSet=Context.Set<T>();
            //shareContext = true;
        }
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (shareContext && (Context != null))
                Context.Dispose();
        }
        /// <summary>
        /// 获取所有的数据
        /// </summary>
        /// <returns></returns>
        public virtual IQueryable<T> All()
        {
            return dbSet.AsQueryable();
        }
        /// <summary>
        /// 通过条件查询到对应的数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual IQueryable<T> Filter(Expression<Func<T, bool>> predicate)
        {
            return dbSet.Where(predicate).AsQueryable<T>();
        }
        /// <summary>
        /// 通过条件查询翻页数据
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="total"></param>
        /// <param name="index"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public virtual IQueryable<T> Filter(Expression<Func<T, bool>> filter, out int total, int index = 0, int size = 50)
        {
            int skipCount = index * size;
            var _resetSet = filter != null ? dbSet.Where(filter).AsQueryable() : dbSet.AsQueryable();
            _resetSet = skipCount == 0 ? _resetSet.Take(size) : _resetSet.Skip(skipCount).Take(size);
            total = _resetSet.Count();
            return _resetSet.AsQueryable();
        }
        /// <summary>
        /// 是否包含对应条件的数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public bool Contains(Expression<Func<T, bool>> predicate)
        {
            return dbSet.Count(predicate) > 0;
        }
        /// <summary>
        /// 通过主键查询数据模型
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public virtual T Find(params object[] keys)
        {
            return dbSet.Find(keys);
        }
        /// <summary>
        /// 通过条件查询数据模型
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual T Find(Expression<Func<T, bool>> predicate)
        {
            return dbSet.FirstOrDefault(predicate);
        }
        /// <summary>
        /// 添加对应数据，返回对应数据模型
        /// </summary>
        /// <param name="TObject"></param>
        /// <returns></returns>
        public virtual T Create(T TObject)
        {
            var newEntry = dbSet.Add(TObject);
            if (!shareContext)
                Context.SaveChanges();
            return newEntry;
        }
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="TObject"></param>
        /// <returns></returns>
        public virtual int Insert(T TObject)
        {
            var newEntry = dbSet.Add(TObject);
            if (!shareContext)
                return Context.SaveChanges();
            return 0;
        }
        /// <summary>
        /// 返回数据个数
        /// </summary>
        public virtual int Count
        {
            get
            {
                return dbSet.Count();
            }
        }
        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="TObject"></param>
        /// <returns></returns>
        public virtual int Delete(T TObject)
        {
            dbSet.Remove(TObject);
            if (!shareContext)
                return Context.SaveChanges();
            return 0;
        }
        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="TObject"></param>
        /// <returns></returns>
        public virtual int Update(T TObject)
        {
            var entry = Context.Entry(TObject);
            dbSet.Attach(TObject);
            entry.State = EntityState.Modified;
            if (!shareContext)
                return Context.SaveChanges();
            return 0;
        }
        /// <summary>
        /// 通过条件删除数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual int Delete(Expression<Func<T, bool>> predicate)
        {
            var objects = Filter(predicate);
            foreach (var obj in objects)
                dbSet.Remove(obj);
            if (!shareContext)
                return Context.SaveChanges();
            return 0;
        }
    }
}
